using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Microsoft.VisualStudio.TestTools.WebTesting;
using WebAndLoadTestPluginsAndRules.Common;

namespace WebAndLoadTestPluginsAndRules.WebTestPlugins
{
    // There is some overlap between this class and WebTestDependentFilter
    // This class incorporates the functionality of the previous class but allows slightly more flexibility in filtering
    // The original class wasn't modified as this would have broken existing tests that use the class

    [DisplayName("Filter Dependent Requests")]
    [Description("Allows dependent requests to be filtered out")]
    public class FilterDependentRequestsPlugin : WebTestPlugin
    {
        private readonly IFilterFactory _filterFactory;

        public FilterDependentRequestsPlugin() : this(new FilterFactory())
        {
        }

        public FilterDependentRequestsPlugin(IFilterFactory filterFactory)
        {
            _filterFactory = filterFactory;
        }

        [DisplayName("Filter")]
        [Description("The filter to match requests to be removed")]
        public string FilterText { get; set; }
        [DisplayName("Filter Method")]
        [Description("Specifies the type of filter to apply")]
        public FilterMethod FilterMethod{ get; set; }
        [DisplayName("Ignore Case")]
        [Description("Ignore case when applying the filter")]
        public bool IgnoreCase { get; set; }

        [DisplayName("Add comment on removal")]
        [Description("True to add a comment to the web test results when a request is filtered out")]
        public bool AddCommentOnRemoval { get; set; }

            
        private Filter _filter;
        protected Filter Filter
        {
            get
            {
                if (_filter == null)
                {
                    _filter = _filterFactory.GetFilter(FilterText, FilterMethod, IgnoreCase);
                }
                return _filter;
            }
        }

        public override void PostRequest(object sender, PostRequestEventArgs e)
        {
            FilterDependentRequests(e.WebTest, e.Request.DependentRequests, Filter, true);
        }

        protected virtual void FilterDependentRequests(WebTest webTest, ICollection<WebTestRequest> dependentRequests, Filter filter, bool addCommentOnRemoval)
        {
            if (dependentRequests == null)
            {
                throw new ArgumentNullException("dependentRequests");
            }
            if (webTest == null)
            {
                throw new ArgumentNullException("webTest");
            }
            List<WebTestRequest> requestsToRemove = dependentRequests.Where(req=> filter.Matches(req.Url)).ToList(); // use separate collection to avoid iterating and modifying
            foreach (WebTestRequest request in requestsToRemove)
            {
                if (addCommentOnRemoval)
                {
                    AddComment(webTest, string.Format("Filter Dependent Requests plugin removed dependent request:'{0}'",
                                                   request.Url));
                }
                dependentRequests.Remove(request);
            }
        }

        protected virtual void AddComment(WebTest webTest, string message)
        {
            webTest.AddCommentToResult(message);
        }
    }
}